package com.yhcnet.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yhcnet.mapper.FileMapper;
import com.yhcnet.pojo.File;
import com.yhcnet.utils.RedisUtils;
import com.yhcnet.utils.Utils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class FileService {
    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 根据用户 id 来获取文件列表
     * @return
     */
    public List<File> getFiles(String uuid,int pid,int page,int type) {
        // 根据 uuid 找到对应的 用户 id
        int uid = (Integer) redisUtils.hget("user", uuid);

        Page<File> filePage = new Page<>(page,10);


        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("uid",uid);

        // -1 代表所有类型
        if (type != -1){
            wrapper.eq("type",type).eq("folder",0);
        }else{
            wrapper.eq("pid",pid);
        }
        wrapper.orderByDesc("update_time");

        Page<File> filePage1 = fileMapper.selectPage(filePage, wrapper);

        return filePage1.getRecords();
    }

    /**
     * 文件搜索
     * @param uuid
     * @param pid
     * @param page
     * @param type
     * @param search
     * @return
     */
    public List<File> getSearch(String uuid,int pid,int page,int type,String search) {
        // 根据 uuid 找到对应的 用户 id
        int uid = (Integer) redisUtils.hget("user", uuid);

        Page<File> filePage = new Page<>(page,10);


        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("uid",uid).eq("pid",pid).like("filename",search);

        // -1 代表所有类型
        if (type != -1){
            wrapper.eq("type",type);
        }

        Page<File> filePage1 = fileMapper.selectPage(filePage, wrapper);

        return filePage1.getRecords();
    }

    /**
     * 文件上传
     * @param file
     * @param uuid
     * @param pid
     * @return
     * @throws IOException
     */
    public boolean upload(MultipartFile file, String uuid, Integer pid) throws IOException {
        // 文件上传逻辑

        // 根据 uuid 找到对应的 用户 id
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        int folder = 0;//是否为文件夹
        String filename = file.getOriginalFilename();//文件名
        String suffix = filename.substring(filename.lastIndexOf(".")).replace(".","");//后缀名
        String newname = UUID.randomUUID().toString()+"."+suffix;//新文件名
        long size = file.getSize() ;//文件大小
        int type = Utils.type(suffix);//文件类型
        int download = 0;//下载次数
        // 判断是否存在现成文件
        String md5 = Utils.md5(file.getBytes());
        QueryWrapper<File> wrapper0 = new QueryWrapper<>();
        wrapper0.eq("md5",md5);
        File file1 = fileMapper.selectOne(wrapper0);
        if(file1 != null) {
            file1.setFid(-1);
            file1.setFilename(filename);
            file1.setPid(pid);
            file1.setUid(uid);
            file1.setDownload(0);
            file1.setCreateTime(null);
        }


        // 保存文件路径
        String path = "files";
        java.io.File nfile = new java.io.File(path);
        String realPath = nfile.getCanonicalPath();
        //如果不存在，创建文件夹
        if (!nfile.exists()) {nfile.mkdirs();}
        file.transferTo(Paths.get(realPath + "/" + newname));
        int insert = 0;
        if(file1 != null){
            insert = fileMapper.insert(file1);
        }else{
            insert = fileMapper.insert(new File(-1, uid, pid, folder, filename, newname, suffix, size, type,1, 0, md5, download, null, null));
        }
        if(pid != -1) {
            QueryWrapper<File> wrapper = new QueryWrapper<>();
            wrapper.eq("fid",pid);
            File updata = fileMapper.selectOne(wrapper);
            if(updata == null) {return false;}
            updata.setSize(updata.getSize() + size);
            updata.setUpdateTime(null);
            int i = fileMapper.updateById(updata);
            if(insert > 0 && i > 0) {return true;}
        }else {
            if(insert > 0) {return true;}
        }

        return false;
    }

    /**
     * 文件夹创建
     * @param name
     * @param uuid
     * @param pid
     * @return
     */
    public boolean create(String name, String uuid, Integer pid) {
        // 根据 uuid 找到对应的 用户 id
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        int folder = 1;//是否为文件夹
        String filename = name;//文件名
        String suffix = null;
        String newname = name;
        double size = 0d;
        int type = 0;
        int download = 0;//下载次数
        String md5 = null;

        int insert = fileMapper.insert(new File(-1, uid, pid, folder, filename, newname, suffix, size, type,1, 0, md5, download, null, null));
        if(insert > 0) {return true;}

        return false;
    }

    /**
     * 下载文件
     * @param response
     * @param fid
     * @param uuid
     * @return
     * @throws IOException
     */
    public boolean download(HttpServletResponse response, int fid, String uuid) throws IOException {
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("fid",fid);
        File file = fileMapper.selectOne(wrapper);
        // 不是该用户或者是文件夹，返回false
        if (file.getUid() != uid || file.getFolder() == 1) {
            return false;
        }
        // 文件路径
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getFilename(),"UTF-8"));
        String path = "files";
        java.io.File target = new java.io.File(path);
        String realPath = target.getCanonicalPath();
        // 获取文件输入流
        InputStream in = new FileInputStream(new java.io.File(realPath+"/"+file.getNewname()));
        // 附件形式下载

        // 获取响应输出流
        IOUtils.copy(in, response.getOutputStream());
        IOUtils.closeQuietly(response.getOutputStream());
        IOUtils.closeQuietly(in);
        file.setFid(fid);
        file.setDownload(file.getDownload() + 1);
        fileMapper.updateById(file);
        return true;
    }

    /**
     * 重命名
     * @param oldName
     * @param suffix
     * @param fid
     * @param uuid
     * @return
     */
    public boolean rename(String oldName, String suffix, int fid, String uuid) {
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("fid",fid);
        File file = fileMapper.selectOne(wrapper);
        if(file.getUid() != uid) {return false;} // 不属于该用户的文件

        //查找该文件夹内有无一样的 name 的文件
        int i = -1;
        //文件夹
        if(suffix == null || suffix.length() == 0) {
            wrapper = new QueryWrapper<>();
            wrapper.eq("filename",oldName).eq("uid",uid).eq("pid",file.getPid());
            File files = fileMapper.selectOne(wrapper);
            if(files != null) {return false;}

            file.setFilename(oldName);
            file.setNewname(oldName);
            i = fileMapper.updateById(file);
        }else { // 不是文件夹，有后缀名
            wrapper = new QueryWrapper<>();
            wrapper.eq("filename",oldName+"."+suffix).eq("uid",uid).eq("pid",file.getPid());
            File files = fileMapper.selectOne(wrapper);
            if(files != null) {return false;}

            file.setFilename(oldName+"."+suffix);
            i = fileMapper.updateById(file);
        }
        if(i > 0) {return true;}

        return false;
    }

    /**
     * 检查文件夹是否重复名
     * @param name
     * @param uuid
     * @param pid
     * @return
     */
    public boolean checkFolder(String name, String uuid, Integer pid) {
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("uid",uid).eq("pid",pid).eq("filename",name);
        File file = fileMapper.selectOne(wrapper);
        if (file != null){return true;}

        return false;
    }

    /**
     * 查重
     * @param file
     * @param uuid
     * @param pid
     * @return
     * @throws IOException
     */
    public boolean checkExsits(MultipartFile file, String uuid,int pid) throws IOException {
        String md5 = Utils.md5(file.getBytes());
        int uid = (Integer) redisUtils.hget("user", uuid);
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.select("fid").eq("uid",uid);
        wrapper.eq("md5",md5);
        wrapper.eq("pid",pid);

        File file1 = fileMapper.selectOne(wrapper);
        if(file1 != null){return true;}

        return false;
    }

    /**
     * 删除文件
     * @param uuid
     * @param fid
     * @return
     */
    public boolean delete(String uuid,int fid) {
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("fid",fid);
        File file = fileMapper.selectOne(wrapper);
        // 删除单个文件
        if (file.getFolder() == 0){
            if (file == null || file.getUid() != uid) {return false;}
            if (fileMapper.deleteById(fid) > 0) {return true;}
        }else{
            // 删除文件夹需要递归删除
            wrapper = new QueryWrapper<>();
            wrapper.eq("pid",file.getFid());
            List<File> files = fileMapper.selectList(wrapper);
            for(File f:files){
                delete(uuid,f.getFid());
            }
            return true;
        }

        return false;
    }

    /**
     * 获取文件总大小
     * @param uuid
     * @return
     */
    public long getSizes(String uuid) {
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("uid",uid);

        if(fileMapper.selectList(wrapper) == null){
            return 0;
        }

        return  fileMapper.selectSizes(uid);
    }

    /**
     * 获取用户在某文件夹下的总文件数
     * @param uuid
     * @param pid
     * @return
     */
    public int getCount(String uuid,int pid,int type) {
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        if (type == -1){
            return fileMapper.selectCount(uid,pid);
        }
        return fileMapper.selectCountByType(uid,pid,type);
    }

    /**
     * 获取文件树
     * @param uuid
     * @param pid
     * @return
     */
    public List<File> getTree(String uuid, int pid) {
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        if(pid == -2){
            ArrayList<File> files = new ArrayList<>();
            files.add(new File(-1,0,0,1,"/","/",null,0,0,0,0,null,0,null,null));
            return files;
        }
        else{
            wrapper.eq("pid",pid).eq("uid",uid).eq("folder",1);
        }

        return fileMapper.selectList(wrapper);
    }

    public boolean moveFiles(String uuid, int fid, int tid) {
        int uid = (Integer) redisUtils.hget("user", uuid);//用户id
        QueryWrapper<File> wrapper = new QueryWrapper<>();
        wrapper.eq("uid",uid).eq("fid",fid);
        File file = fileMapper.selectOne(wrapper);
        if (file == null){
            return false;
        }

        file.setUpdateTime(null);
        file.setPid(tid);

        int i = fileMapper.updateById(file);

        return i>0;
    }
}
